#include "WebServer.h"
#include "main.hpp"

extern DeviceConf deviceConf;

//配网页面代码
const char *page_html = "\
<!DOCTYPE html>\r\n\
<html lang='en'>\r\n\
<head>\r\n\
  <meta charset='UTF-8'>\r\n\
  <meta name='viewport' content='width=device-width, initial-scale=1.0'>\r\n\
  <title>Document</title>\r\n\
</head>\r\n\
<body>\r\n\
  <form name='input' action='/submit_wifi_info' method='POST'>\r\n\
        wifi名称: <br>\r\n\
        <input type='text' name='ssid'><br>\r\n\
        wifi密码:<br>\r\n\
        <input type='text' name='password'><br>\r\n\
        <input type='submit' value='保存'>\r\n\
    </form>\r\n\
</body>\r\n\
</html>\r\n\
";

//修改时间页面代码
const char *conf_html = "<!DOCTYPE html>\r\n\
<html lang=\"zh-CN\">\r\n\
\r\n\
<head>\r\n\
    <meta charset=\"utf-8\">\r\n\
    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\r\n\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n\
    <title>辉光管时钟</title>\r\n\
</head>\r\n\
\r\n\
<body>\r\n\
    <div class=\"container\">\r\n\
        <div class=\"starter-template\">\r\n\
            <h1>选择你喜欢的配置......</h1>\r\n\
        </div>\r\n\
        <div class=\"starter-template\">\r\n\
            <h3>设置完了记得保存！！！</h3>\r\n\
            <hr>\r\n\
            <form name='input' action='/submit_conf' method='POST'>\r\n\
                <p>\r\n\
                <h3>氛围灯配置</h3>\r\n\
                <b><input type=\"checkbox\" name=\"led_enable\" id=\"led_enable\" onchange=\"colorChange()\">氛围灯开关</b><br>\r\n\
                <script type=\"text/javascript\">\r\n\
                    function colorChange() {\r\n\
                        var value = document.getElementById('led_enable').checked;\r\n\
                        var colorConfItems = document.getElementsByName('color_conf');\r\n\
                        for (let index = 0; index < colorConfItems.length; index++)\r\n\
                            colorConfItems[index].disabled = !value;\r\n\
                        var colorValue = document.getElementById('led_color').disabled = !value;\r\n\
                    }\r\n\
                </script>\r\n\
                <div id=\"form_color_conf\">\r\n\
                    <input type=\"radio\" name=\"color_conf\" value=\"default_color_conf_1\" checked>土嗨跑马灯<br>\r\n\
                    <input type=\"radio\" name=\"color_conf\" value=\"default_color_conf_2\">土嗨跑马呼吸灯<br>\r\n\
                    <input type=\"radio\" name=\"color_conf\" value=\"default_color_conf_3\">固定颜色显示<br>\r\n\
                    <input type=\"radio\" name=\"color_conf\" value=\"custom_color_conf\">固定颜色呼吸灯<br>\r\n\
                    颜色设置：<input type=\"color\" name=\"led_color\" id=\"led_color\">\r\n\
                </div>\r\n\
                </p>\r\n\
                <br>\r\n\
                <p>\r\n\
                <h3>时间配置</h3>\r\n\
                时区设置：\r\n\
                <select name=\"timezone_offset\" id=\"timezone_offset\">\r\n\
                    <option value=\"-12\">Eniwetok, Kwajalein</option>\r\n\
                    <option value=\"-11\">Midway Island, Samoa</option>\r\n\
                    <option value=\"-10\">Hawaii</option>\r\n\
                    <option value=\"-9\">Alaska</option>\r\n\
                    <option value=\"-8\">Pacific Time (US & Canada)</option>\r\n\
                    <option value=\"-7\">Mountain Time (US & Canada)</option>\r\n\
                    <option value=\"-6\">Central Time (US & Canada), Mexico City</option>\r\n\
                    <option value=\"-5\">Eastern Time (US & Canada), Bogota, Lima</option>\r\n\
                    <option value=\"-4\">Atlantic Time (Canada), Caracas, La Paz</option>\r\n\
                    <option value=\"-3\">Brazil, Buenos Aires, Georgetown</option>\r\n\
                    <option value=\"-2\">Mid-Atlantic</option>\r\n\
                    <option value=\"-1\">Azores, Cape Verde Islands</option>\r\n\
                    <option value=\"0\">Western Europe Time, London, Lisbon</option>\r\n\
                    <option value=\"1\">CET(Central Europe Time), Madrid, Paris, Rome</option>\r\n\
                    <option value=\"2\">EET(Eastern Europe Time), Kaliningrad, South Africa</option>\r\n\
                    <option value=\"3\">Baghdad, Kuwait, Moscow, Nairobi</option>\r\n\
                    <option value=\"4\">Abu Dhabi</option>\r\n\
                    <option value=\"5\">Islamabad, Karachi</option>\r\n\
                    <option value=\"6\">Almaty, Dhaka, Colombo</option>\r\n\
                    <option value=\"7\">Bangkok, Hanoi, Jakarta</option>\r\n\
                    <option value=\"8\" selected>Beijing, Perth, Singapore, Hong Kong, Taipei</option>\r\n\
                    <option value=\"9\">Tokyo</option>\r\n\
                    <option value=\"10\">EAST(East Australian Standard)</option>\r\n\
                    <option value=\"11\">New Caledonia</option>\r\n\
                    <option value=\"12\">Auckland</option>\r\n\
                </select>\r\n\
                <br>休眠时间设置：<input type=\"time\" name=\"sleep_time_start\" id=\"sleep_time_start\"> ~ <input type=\"time\" name=\"sleep_time_end\" id=\"sleep_time_end\">\r\n\
                </p>\r\n\
                <br>\r\n\
                <p>\r\n\
                <h3>辉光管配置</h3>\r\n\
                <b><input type=\"checkbox\" name=\"env_data_enable\" id=\"env_data_enable\">显示温湿度数据</b>\r\n\
                </p>\r\n\
                <br><input type='submit' value='保存'>\r\n\
                <p>提交状态: <span id=\"result\"></span></p>\r\n\
            </form>\r\n\
        </div>\r\n\
    </div>\r\n\
\r\n\
    <script type=\"text/javascript\">\r\n\
        window.onload = function () {\r\n\
            console.log(\"init...\");\r\n\
            colorChange();\r\n\
            var xmlhttp;\r\n\
            xmlhttp = new XMLHttpRequest();\r\n\
            xmlhttp.onreadystatechange = function () {\r\n\
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {\r\n\
                    document.getElementById(\"result\").innerHTML = xmlhttp.responseText;\r\n\
                    var jsonConf = JSON.parse(xmlhttp.responseText)\r\n\
                    document.getElementById(\"led_enable\").checked = jsonConf.ledState\r\n\
                    colorChange()\r\n\
                    if (jsonConf.ledMode)\r\n\
                        document.getElementsByName(\"color_conf\")[jsonConf.ledMode - 1].checked = true\r\n\
                    if (jsonConf.colorValue)\r\n\
                        document.getElementById(\"led_color\").value = jsonConf.colorValue\r\n\
                    if (jsonConf.timezoneOffset)\r\n\
                        document.getElementById(\"timezone_offset\").value = jsonConf.timezoneOffset\r\n\
                    if (jsonConf.startSleepTime)\r\n\
                        document.getElementById(\"sleep_time_start\").value = jsonConf.startSleepTime\r\n\
                    if (jsonConf.endSleepTime)\r\n\
                        document.getElementById(\"sleep_time_end\").value = jsonConf.endSleepTime\r\n\
                    if (jsonConf.envDataEnable)\r\n\
                        document.getElementById(\"env_data_enable\").checked = jsonConf.envDataEnable\r\n\
                    console.log(\"init...\")\r\n\
                }\r\n\
            }\r\n\
            var requestString = \"/get_conf\"\r\n\
            console.log(\"req:\" + requestString);\r\n\
            xmlhttp.open(\"GET\", requestString, true);\r\n\
            xmlhttp.send(null);\r\n\
        }\r\n\
    </script>\r\n\
</body>\r\n\
\r\n\
</html>";

DNSServer dnsServer;            //创建dnsServer实例
ESP8266WebServer server(80);    //创建WebServer
IPAddress apIP(192, 168, 4, 1); // esp8266-AP-IP地址
extern void connectNewWifi(char *ssid, char *passwd);

void initWebServer(void)
{ //初始化WebServer
    // server.on("/",handleRoot);
    //上面那行必须以下面这种格式去写否则无法强制门户
    server.on("/", HTTP_GET, handleRoot);                      //设置主页回调函数
    server.onNotFound(handleRoot);                             //设置无法响应的http请求的回调函数
    server.on("/submit_wifi_info", HTTP_POST, handleRootPost); //设置Post请求回调函数
    server.begin();                                            //启动WebServer
}

void initDNS(void)
{ //初始化DNS服务器
    if (dnsServer.start(DNS_PORT, "*", apIP))
    { //判断将所有地址映射到esp8266的ip上是否成功
        Serial.println("start dnsserver success.");
    }
    else
        Serial.println("start dnsserver failed.");
}

void initConfWeb()
{
    dnsServer.stop();
    server.stop();
    //初始化DNS服务器
    if (dnsServer.start(DNS_PORT, "www.zeseye.com", apIP))
        Serial.println("start dnsserver success."); //判断将所有地址映射到esp8266的ip上是否成功
    else
        Serial.println("start dnsserver failed.");
    server.on("/", HTTP_GET, handleConfRoot);            //设置主页回调函数
    server.on("/get_conf", HTTP_GET, handleGetConf);     //设置主页回调函数
    server.on("/submit_conf", HTTP_POST, handleSetConf); //设置主页回调函数
    server.begin();
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
    if (WiFi.softAP("Zeseye", "Zeseye0311"))
    {
        Serial.println("ESP8266 SoftAP is right");
    } //启动WebServer
}

void handleRoot()
{ //访问主页回调函数
    server.send(200, "text/html", page_html);
}

void handleConfRoot()
{ //访问主页回调函数
    server.send(200, "text/html", conf_html);
}

void handleGetConf()
{ //访问主页回调函数
    Serial.println("handleSetConf");
    StaticJsonDocument<300> doc;
    doc["ledState"] = deviceConf.ledState_;
    doc["ledMode"] = deviceConf.ledMode_;
    char tempStr[10] = {0};
    sprintf(tempStr, "#%02x%02x%02x", (deviceConf.colorValue_ >> 16 & 0xff), (deviceConf.colorValue_ >> 8 & 0xff), (deviceConf.colorValue_ & 0xff));
    doc["colorValue"] = String(tempStr);
    doc["timezoneOffset"] = deviceConf.timezoneOffset_;
    if (deviceConf.startSleepTime_ != 0xffffffff && deviceConf.endSleepTime_ != 0xffffffff)
    {
        sprintf(tempStr, "%02d:%02d", deviceConf.startSleepTime_ / 3600, deviceConf.startSleepTime_ / 60 % 60);
        doc["startSleepTime"] = String(tempStr);
        sprintf(tempStr, "%02d:%02d", deviceConf.endSleepTime_ / 3600, deviceConf.endSleepTime_ / 60 % 60);
        doc["endSleepTime"] = String(tempStr);
    }
    doc["envDataEnable"] = deviceConf.envDataEnable_;
    String result;
    serializeJson(doc, result);
    server.send(200, "text/html", result.c_str()); //返回保存成功页面
}

void handleSetConf()
{
    Serial.println("handleSetConf");
    if (server.hasArg("led_enable"))
    { //判断是否有账号参数
        deviceConf.ledState_ = 1;
        if (server.hasArg("color_conf"))
        {
            if (server.arg("color_conf").compareTo("default_color_conf_1") == 0)
                deviceConf.ledMode_ = LED_MODE_DYNAMIC;
            if (server.arg("color_conf").compareTo("default_color_conf_2") == 0)
                deviceConf.ledMode_ = LED_MODE_DYNAMIC_BREATH;
            if (server.arg("color_conf").compareTo("default_color_conf_3") == 0)
                deviceConf.ledMode_ = LED_MODE_STATIC;
            if (server.arg("color_conf").compareTo("custom_color_conf") == 0)
                deviceConf.ledMode_ = LED_MODE_STATIC_BREATH;
            Serial.print("got led_mode:");
            Serial.println(deviceConf.ledMode_);
        }
        if (server.hasArg("led_color"))
        {
            u8 r, g, b;
            sscanf(server.arg("led_color").c_str(), "#%02x%02x%02x", &r, &g, &b);
            deviceConf.colorValue_ = (r << 16) | (g << 8) | b;
            Serial.print("got led_color:");
            Serial.println(deviceConf.colorValue_);
        }
        Serial.print("got led_enable:");
        Serial.println(server.arg("led_enable").c_str());
    }
    else
    {
        deviceConf.ledState_ = 0;
    }
    if (server.hasArg("timezone_offset"))
    {
        deviceConf.timezoneOffset_ = server.arg("timezone_offset").toInt();
        Serial.print("got timezone_offset:");
        Serial.println(deviceConf.timezoneOffset_);
    }
    if (server.hasArg("sleep_time_start") && server.hasArg("sleep_time_end"))
    {
        String sleepTimeStartConf = server.arg("sleep_time_start");
        String sleepTimeEndConf = server.arg("sleep_time_end");
        Serial.println(sleepTimeStartConf);
        Serial.println(sleepTimeEndConf);
        if (!sleepTimeStartConf.isEmpty() && !sleepTimeEndConf.isEmpty())
        {
            int hour, minute;
            sscanf(sleepTimeStartConf.c_str(), "%2d:%2d", &hour, &minute);
            deviceConf.startSleepTime_ = hour * 60 * 60 + minute * 60;
            sscanf(sleepTimeEndConf.c_str(), "%2d:%2d", &hour, &minute);
            deviceConf.endSleepTime_ = hour * 60 * 60 + minute * 60;
            Serial.println(deviceConf.startSleepTime_);
            Serial.println(deviceConf.endSleepTime_);
        }
        else
        {
            deviceConf.startSleepTime_ = 0xffffffff;
            deviceConf.endSleepTime_ = 0xffffffff;
        }
    }
    if (server.hasArg("env_data_enable"))
    {
        deviceConf.envDataEnable_ = SHOW_ENV_DATA;
        Serial.print("got env_data_enable:");
        Serial.println(deviceConf.envDataEnable_);
    }
    else
    {
        deviceConf.envDataEnable_ = SHOW_ONLY_TIME;
    }
    WriteConf();
    SaveConf();
    PrintConf();
    ApplyConf();
    server.send(200, "text/html", "<meta charset='UTF-8'>保存成功"); //返回保存成功页面
}

void handleRootPost()
{ // Post回调函数
    //暂时存储wifi账号密码
    char sta_ssid[32] = {0};
    char sta_password[32] = {0};
    Serial.println("handleRootPost");
    if (server.hasArg("ssid"))
    { //判断是否有账号参数
        Serial.print("got ssid:");
        strcpy(sta_ssid, server.arg("ssid").c_str()); //将账号参数拷贝到sta_ssid中
        Serial.println(sta_ssid);
    }
    else
    { //没有参数
        Serial.println("error, not found ssid");
        server.send(200, "text/html", "<meta charset='UTF-8'>error, not found ssid"); //返回错误页面
        return;
    }
    //密码与账号同理
    if (server.hasArg("password"))
    {
        Serial.print("got password:");
        strcpy(sta_password, server.arg("password").c_str());
        Serial.println(sta_password);
    }
    else
    {
        Serial.println("error, not found password");
        server.send(200, "text/html", "<meta charset='UTF-8'>error, not found password");
        return;
    }

    server.send(200, "text/html", "<meta charset='UTF-8'>保存成功"); //返回保存成功页面
    delay(2000);
    //连接wifi
    connectNewWifi(sta_ssid, sta_password);
}

void WebServerProcess()
{
    server.handleClient();
    dnsServer.processNextRequest();
}
